<template>
	<view class="pagebox flex-column">
		<template>
			<navtop></navtop>
			<view class="bg" @click="$c.go_url('/pages/login')"></view>
			
			<view class="bottombox">
				<view class="chartbox flex-row-center">
					<!-- <view class="voicebox flex-center">
						<image class="voiceicon" src="../../static/5.png" mode="aspectFill"></image>
					</view> -->
					<view class="inputbox flex-row-center">
						<input type="text" v-model="obj.chatMsg" placeholder="请在此输入您要提问的内容" />
						<image class="addicon" src="../../static/6.png" mode="aspectFill" @click="obj.showMod=true"></image>
					</view>
					<view v-if="obj.chatMsg" class="send" @click="sendInut(obj.chatMsg)">发送</view>
				</view>
				<template v-if="obj.showMod">
					<view class="desc">内容由大模型生成，不能完全保障真实</view>
					<view class="modbox flex-row wrap">
						<view class="mod flex-column-center" v-for="(v,i) in obj.mods" :key="i" @click="selectMod(v)">
							<view class="item flex-center"><image class="" src="../../static/6.png" mode="aspectFill"></image></view>
							<text class="name">{{v.name}}</text>
						</view>
					</view>
				</template>
			</view>
		</template>
		
		<template>
			<view :style="{height:`${obj.wh.navHeight+10}px`,width: '100vw'}"></view>
			<template>
				<!-- 小丝 -->
				<template v-if="!obj.messages.length">
					<view class="lefthead">
						<image class="head" src="../../static/logo.png" mode="aspectFill"></image>
					</view>
					<view class="xiaosi_chart">
						<view class="title">Hi，我是小丝！</view>
						<text class="desc">{{obj.mod.desc}}</text>
					</view>
					<view class="recommend">
						<view class="flex-row-center ju-between">
							<text class="re-label">推荐智能体</text>
							<image class="refresh" src="../../static/6.png" mode="aspectFill" @click="refreshProblem"></image>
						</view>
						<view class="problem" v-for="(v,i) in obj.problems" :key="i" @click="sendRecommend(v)">{{v.title}}</view>
						<view v-if="!obj.problems.length" class="nodata">暂无推荐</view>
					</view>
				</template>
				<template v-for="(item,index) in obj.messages" :key="i">
					<view class="problem_chart" v-if="item.role=='user'">
						{{item.content}}
					</view>
					<view class="answer_chart flex-column" v-if="item.role=='assistant'">
						<zero-markdown-view :markdown="item.content"></zero-markdown-view>
						<view class="recommends flex-column" v-if="item.recommends">
							<view class="recommendDesc">{{obj.mod.recommendDesc}}</view>
							<view class="name mt10" v-for="(v,i) in item.recommends" :key="i" @click="changeRecommend(v)">{{v.name}}</view>
							<view class="w100 flex-center base-color f26 mt30" @click="proxy.$c.go_url('/pages/products')">更多产品</view>
						</view>
						<view v-if="item.recommends" class="desc">内容由大模型生成，不能完全保障真实</view>
					</view>
				</template>
			</template>
			<view id="bottom_space" :style="{height:`140rpx`,width: '100vw'}"></view>
		</template>
	</view>
</template>

<script setup>
    import { reactive, getCurrentInstance,onMounted,watch } from 'vue'
    let { proxy } = getCurrentInstance()
	// let textDecoder = new TextDecoder('utf-8')
	let obj = reactive({
		wh: proxy.$c.getglobal(),
		mods: [
			{name: '热门问题', url: '', type: 0, desc: '您可以选择以下热门问题！', recommend: '请向我推荐三条热门问题，请返回知识库中的前三列，其他均不要，以清晰的 JSON 格式呈现，JSON字段分别为id和name，且内容必须为中文', recommendDesc: '关于丝网问题，大家最热门的问题如下：' },
			{name: '产品中心', url: '', type: 1, desc: '我可以为你提供产品中心相关的帮助！', recommend: '请向我推荐三条丝网产品，请返回知识库中的前三列，其他均不要，以清晰的 JSON 格式呈现，JSON字段分别为id和name，且内容必须为中文', recommendDesc: '根据目前的产品清单，帮你推荐如下产品：' },
			{name: '身份认证', url: '/pages/authentication' },
			{name: '聊天信息', url: '/pages/chartHistory' },
			{name: '企业制度', url: '', type: 2, desc: '您可以问我一些身份认证相关问题！' }
		],
		mod: {name: '热门问题', url: '', type: 0, desc: '您可以选择以下热门问题！' },
		chatMsg: '',
		showMod: false,
		proReq: {
			type: 0,
			currentpage: 1,
			pagesize: 3
		},
		type: 0,//0热门问题 1产品中心 2企业制度
		problems: [],
		messages: [],
		recommends: null,
		isChartEnd: 0,//初始化 聊天成功 聊天失败
	})
	
	onMounted(()=>{
		obj.mod = obj.mods[0]
		getproblem()
	})
	
	const selectMod=(v)=>{
		obj.showMod = false
		if(v.url){
			proxy.$c.go_url(v.url)
		}else{
			if(obj.mod.name==v.name){
				return
			}
			obj.messages = []
			obj.mod = v
			obj.proReq.type = v.type
			obj.proReq.currentpage = 1
			getproblem()
		}
	}
	
	const getproblem=()=>{
		proxy.$reQuest.post('mp/problem/list',obj.proReq,{token: true},).then(res=>{
			if(res.success){
				obj.problems = res.msg.list||[]
				obj.proCount = res.msg.count||0
			}else{
				obj.problems = []
			}
		}).catch(err=>{obj.problems = []})
	}
	
	const refreshProblem=()=>{
		if(obj.proCount>obj.proReq.currentpage*obj.proReq.pagesize){
			obj.proReq.currentpage++
		}else{
			obj.proReq.currentpage = 1
		}
		getproblem()
	}
	
	const getToken=()=>{
	    return new Promise((resolve, reject) => {
			proxy.$reQuest.post('mp/getToken',{},{token: true},).then(res=>{
				resolve(res.msg||"")
			}).catch(err=>{resolve('')})
		})
	}
	
	const getChartObj=async(content)=>{
		let token = await getToken()
		return new Promise((resolve, reject) => {
		    uni.request({
		        // url: 'https://open.bigmodel.cn/api/paas/v4/chat/completions', //前端调用
		    	url: 'https://silkscreen.server.zhhost.top/v1/chat/completions',//后端pyrhon调用
		        method: "POST", // 你的请求方法
		        data: {
		    		model: 'glm-4-long',
		    		messages: [
						{
							"role": "user",
							"content": content
						}
					],
		    		stream: false,//是否流式
		    	},
		        header: {
		            // "Accept": 'text/event-stream',
		            "Content-Type": "application/json;charset=UTF-8;",
		    		"Authorization": token
		        },
		    	dataType: 'json',
		        // responseType: "text",
		        enableChunked: false, // 开启流传输
		        success: (res) => {
					console.log('res1',res);
					if(res.data){
						const str = `[${res.data.slice(0, -1)}]`
						const d = JSON.parse(str)
						let objstr  = ''
						objstr += d.map(t => t.content).join('')
						console.log('objstr',objstr);
						if(objstr.indexOf("```json")!=-1){
							// console.log('objstr.slice(7,-3)',objstr.slice(7,-3));
							// const matchReg = 
							const objstr_ = objstr.match(/(?<=```json)([\s\S]*?)(?=```)/g)
							console.log('objstr_',objstr_);
							resolve(JSON.parse(objstr_[0]))
						}else{
							resolve(null)
						}
					}else{
						resolve(null)
					}
		        },
		        fail: (err) => {
		            resolve(null)
		        },
		    })
		})
	}
	
	const StreamRequest=async(messages,type)=>{
		let token = await getToken()
	    return new Promise((resolve, reject) => {
	        const response = uni.request({
	            // url: 'https://open.bigmodel.cn/api/paas/v4/chat/completions', //前端调用
				url: 'https://silkscreen.server.zhhost.top/v1/chat/completions',//后端pyrhon调用
	            method: "POST", // 你的请求方法
	            data: {
					model: 'glm-4-long',
					messages: messages,
					stream: true,//是否流式
				},
	            header: {
	                // "Accept": 'text/event-stream',
	                "Content-Type": "application/json;charset=UTF-8;",
					"Authorization": token
	            },
				dataType: 'json',
	            // responseType: "text",
	            enableChunked: true, // 开启流传输
	            success: async(res) => {
					//调用结束
					console.log('res',res);
					if(res.statusCode==200){
						obj.isChartEnd = 1
						if(type==='recommend'){
							if(obj.mod.recommend){
								const len = obj.messages.length-1
								if(!obj.messages[len].recommends&&obj.recommends){
									obj.messages[len].recommends = obj.recommends||null//灰色区域 推荐内容
									console.log('a')
									addchat()
									uni.pageScrollTo({selector: '#bottom_space'})
								}
							}
						}else{
							console.log('b')
							addchat()
						}
					}else{
						obj.isChartEnd = 2
						const len = obj.messages.length-1
						obj.messages[len].content = `生成失败，失败码${res.statusCode}，请稍后再试...`
					}
	            },
	            fail: (err) => {
					obj.isChartEnd = 2
					console.log('err2',err);
					const len = obj.messages.length-1
					obj.messages[len].content = '生成失败，请稍后再试...'
	            },
	        })
	        // 返回请求的响应
	        resolve(response)
	    })
	}
	
	const ab2strEfficient=(buf)=>{  
		  return Array.from(new Uint8Array(buf), byte => String.fromCharCode(byte)).join('');  
	}
	
	const getchat=async(messages,type)=>{
		try {
			const requestTask = await StreamRequest(messages,type)
			// 成功回调 返回流传输信息 返回arrayBuffer
			requestTask.onChunkReceived((e)=>{
				const chunkText_ = ab2strEfficient(e.data)
				const chunkText = decodeURIComponent(escape(chunkText_));
				console.log('chunkText',chunkText);
				// 后端pyrhon调用处理
				const str = `[${chunkText.slice(0, -1)}]`
				const d = JSON.parse(str)
				const c = obj.messages[obj.messages.length-1].content||''
				obj.messages[obj.messages.length-1].content = c=='生成中...'?'':c
				obj.messages[obj.messages.length-1].content += d.map(t => t.content).join('')
				uni.pageScrollTo({selector: '#bottom_space'})
				// 前端调用处理
				// const d = JSON.parse(chunkText.split('data: ')[1])
				// if(d?.choices?.length){
				// 	const c = obj.messages[obj.messages.length-1].content||''
				// 	obj.messages[obj.messages.length-1].content = c=='生成中...'?'':c
				// 	obj.messages[obj.messages.length-1].content += d.choices[0].delta.content||'';
				// }
			})
		} catch (err) {
			const len = obj.messages.length-1
			obj.messages[len].content = '生成失败，请稍后再试...'
		}
	}
	
	const setchart=async(msg,type)=>{
		obj.isChartEnd = 0
		const u = {
			"role": "user",
			"content": msg.title
		}
		const messages = obj.messages.concat([u])
		
		getchat(JSON.parse(JSON.stringify(messages)),type)
		obj.messages = messages.concat([{
			role: 'assistant',
			content: '生成中...',
			recommends: null//灰色区域 推荐内容
		}])
		uni.pageScrollTo({selector: '#bottom_space'})
		
		if(type==='recommend'&&obj.mod.recommend){
			obj.recommends = await getChartObj(obj.mod.recommend)//灰色区域 推荐内容
			const len = obj.messages.length-1
			if(obj.isChartEnd==1&&!obj.messages[len].recommends){
				console.log('c',obj.messages[len].recommends);
				obj.messages[len].recommends = obj.recommends||null
				console.log('c')
				addchat()
				uni.pageScrollTo({selector: '#bottom_space'})
			}
		}
	}
	
	const sendRecommend=async(v)=>{
		setchart(v,'recommend')
	}
	
	const sendInut=(msg)=>{
		setchart({title:msg},'chart')
		obj.chatMsg = ''
	}
	
	const changeRecommend=(v)=>{
		console.log('点击推荐：',v);
		if(obj.mod.type==0){
			
		}else if(obj.mod.type==1){
			proxy.$c.go_url(`/pages/productDetail?id=${v.id}`)
		}else if(obj.mod.type==2){
			
		}
	}
	
	const addchat=()=>{
		const len = obj.messages.length-1
		const q = obj.messages[len-1]
		const a = obj.messages[len]
		proxy.$reQuest.post('mp/user/chat/add',{
			q: q.content,
			a: a.content,
			other: a.recommends?JSON.stringify(a.recommends):'',
			type: obj.mod.type
		},{token: true},).then(res=>{
			if(res.success){
				obj.companys = res.msg.list||[]
			}else{
				obj.companys = []
			}
		}).catch(err=>{obj.companys = []})
	}
	
	
</script>

<style lang="scss" scoped>
	.pagebox{
		width: 750rpx;padding: 0 30rpx;box-sizing: border-box;font-size: 26rpx;
		.bg{
			position: fixed;left: 0;top: 0;z-index: -1;
			width: 750rpx;height: 430rpx;
			background: linear-gradient( 180deg, #BCE5F7 0%, #fff 100%);
		}
		.bottombox{
			position: fixed;left: 0;bottom: 0; z-index: 9999999;background: #fff;box-shadow: 0 -10rpx 10rpx 10rpx rgba(0,0,0,0.03);padding: 20rpx 30rpx;box-sizing: border-box;
			.chartbox{
				width: 690rpx;margin-bottom: 10rpx;
				.voicebox{
					width: 80rpx;min-width: 80rpx;height: 80rpx;border: 2rpx solid #D9DBE4;border-radius: 76rpx;margin-right: 20rpx;
					.voiceicon{width: 50rpx;height: 50rpx;}
				}
				.inputbox{
					flex: 1;height: 80rpx;border-radius: 80rpx;border: 2rpx solid #D9DBE5;
					padding: 0 20rpx 0 30rpx;box-sizing: border-box;font-size: 26rpx;
					input{flex: 1;}
					.addicon{width: 40rpx;height: 40rpx;}
				}
				.send{height: 80rpx;border-radius: 80rpx;padding: 0 30rpx;box-sizing: border-box; margin-left: 10rpx;background: #1773E5;display: flex;align-items: center;justify-content: center;font-size: 26rpx;color: #fff;}
			}
			.desc{width: 100%;font-size: 22rpx;color: #999;text-align: right;margin-bottom: 20rpx;}
			.modbox{
				.mod{
					width: 25%;margin-bottom: 30rpx;
					.item{
						width: 120rpx;height: 118rpx;background: #FFFFFF;box-shadow: 0rpx 5rpx 13rpx 0rpx #EDEDED;border-radius: 20rpx;margin-bottom: 20rpx;
						image{width: 42rpx;height: 42rpx;}
					}
					.name{font-size: 26rpx;}
				}
			}
		}
		
		.lefthead{
			width: 60rpx;height: 60rpx;border-radius: 60rpx;overflow: hidden;margin-bottom: 10rpx;image{width: 60rpx;height: 60rpx;}
		}
		.xiaosi_chart{
			width: 690rpx;height: auto;box-shadow: 0rpx 2rpx 7rpx 0rpx rgba(170,192,224,0.5);border-radius: 0rpx 25rpx 25rpx 25rpx;border: 2rpx solid rgba(255,255,255,0.3);
			padding: 20rpx 30rpx;box-sizing: border-box;margin-bottom: 40rpx;
			background: linear-gradient( 86deg, #E2EEFF 0%, #EAECFF 100%);
			.title{font-size: 33rpx;font-weight: bold;color: #5289E8;margin-bottom: 5rpx;}
			.desc{font-size: 25rpx;color: #999;}
		}
		.recommend{
			position: relative;
			width: 690rpx;height: auto;background: #FFFFFF;box-shadow: 0rpx 4rpx 16rpx 0rpx #DAE3EF;border-radius: 0rpx 25rpx 25rpx 25rpx;
			padding: 20rpx 30rpx;box-sizing: border-box;margin-bottom: 40rpx;
			.re-label{font-size: 30rpx;font-weight: bold;position: relative;z-index: 2;}
			.re-label::before{content: '';display: block;position: absolute;left: 0;bottom: 10rpx;z-index: 1;width: 114rpx;height: 11rpx;background: linear-gradient( 90deg, #3D8BFF 0%, rgba(251,251,251,0) 100%);opacity: 0.75;}
			.refresh{width: 30rpx;height: 30rpx;}
			.problem{padding: 30rpx 0;box-sizing: border-box;font-size: 26rpx;border-bottom: 1rpx solid #F3F3F3;}
			.problem:last-child{border: none;}
			.nodata{width: 100%;padding: 60rpx;box-sizing: border-box;text-align: center;font-size: 22rpx;color: #999;}
		}
		
		.problem_chart{
			width: fit-content;max-width: 690rpx;height: auto;display: inline-flex;background: #1773E5;border-radius: 0rpx 18rpx 18rpx 18rpx;color: #fff;
			padding: 20rpx 30rpx;box-sizing: border-box;margin-bottom: 40rpx;
		}
		.answer_chart{
			width: auto;max-width: 690rpx;height: auto;display: inline-flex;background: linear-gradient( 82deg, #F5F6F8 0%, #F5F6F8 100%);box-shadow: 0rpx 0rpx 9rpx 0rpx #EDF0F5;border-radius: 0rpx 25rpx 25rpx 25rpx;border: 1rpx solid #E1E8F8;
			padding: 20rpx;box-sizing: border-box;margin-bottom: 40rpx;
			.recommends{
				padding: 20rpx;border-radius: 10rpx;background: #ECEDF0;margin-bottom: 10rpx;
				font-size: 26rpx;
				.recommendDesc{
					color: #999;margin-bottom: 10rpx;
				}
				.name{
					color: #1773E5;
				}
			}
			.desc{width: 100%;text-align: right;font-size: 22rpx;color: #999;}
		}
	}
</style>
